/** * Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onebusaway.webapp.gwt.oba_application.search; import org.onebusaway.geospatial.model.CoordinateBounds; import org.onebusaway.transit_data.model.oba.LocalSearchResult; import org.onebusaway.webapp.gwt.common.rpc.JsonCallback; import org.onebusaway.webapp.gwt.common.rpc.JsonLibrary; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; import com.google.gwt.maps.client.geom.LatLng; import java.util.ArrayList; import java.util.List; public class YelpLocalSearchProvider implements LocalSearchProvider { private static final String YELP_API_BUSINESS_REVIEW_SEARCH = "http://api.yelp.com/business_review_search"; private final String _apiKey; private int _requestId = 0; private int _maxResultCount = 20; private int _timeout = 3000; public YelpLocalSearchProvider(String apiKey) { _apiKey = apiKey; } public void setMaxResultCount(int maxResultCount) { _maxResultCount = maxResultCount; } public void setTimeout(int timeout) { _timeout = timeout; } public void search(CoordinateBounds bounds, String query, String category, LocalSearchCallback callback) { StringBuilder url = buildQuery(query, category); url.append("&tl_lat=").append(bounds.getMaxLat()); url.append("&tl_long=").append(bounds.getMinLon()); url.append("&br_lat=").append(bounds.getMinLat()); url.append("&br_long=").append(bounds.getMaxLon()); performQuery(url, callback); } public void search(LatLng center, String query, String category, LocalSearchCallback callback) { StringBuilder url = buildQuery(query, category); url.append("&lat=").append(center.getLatitude()); url.append("&long=").append(center.getLongitude()); performQuery(url, callback); } public void searchByRadius(LatLng center, double radius, String query, String category, LocalSearchCallback callback) { StringBuilder url = buildQuery(query, category); url.append("&lat=").append(center.getLatitude()); url.append("&long=").append(center.getLongitude()); url.append("&radius=").append(radius); performQuery(url, callback); } private StringBuilder buildQuery(String query, String category) { StringBuilder url = new StringBuilder(); url.append(YELP_API_BUSINESS_REVIEW_SEARCH); url.append("?term=").append(query); if (category != null && category.length() > 0) url.append("&category=").append(category); url.append("&num_biz_requested=" + _maxResultCount); url.append("&ywsid=").append(_apiKey); return url; } private void performQuery(StringBuilder url, LocalSearchCallback callback) { url.append("&callback="); JsonHandler handler = new JsonHandler(callback); JsonLibrary.getJson("yelp" + (_requestId++), url.toString(), handler, _timeout); } private static class JsonHandler implements JsonCallback { private LocalSearchCallback _handler; public JsonHandler(LocalSearchCallback handler) { _handler = handler; } public void onSuccess(JavaScriptObject jso) { try { JSONObject obj = new JSONObject(jso); checkStatusCode(obj); JSONArray businesses = JsonLibrary.getJsonArray(obj, "businesses"); if (businesses == null) throw new YelpException("invalid businesses field in response"); List<LocalSearchResult> results = new ArrayList<LocalSearchResult>( businesses.size()); for (int i = 0; i < businesses.size(); i++) { LocalSearchResult result = parseResult(businesses.get(i)); if (result != null) results.add(result); } _handler.onSuccess(results); } catch (YelpException ex) { _handler.onFailure(ex); } } public void onFailure() { _handler.onFailure(new YelpTimeoutException()); } private void checkStatusCode(JSONObject obj) throws YelpException, YelpStatusException { JSONObject messages = JsonLibrary.getJsonObj(obj, "message"); if (messages == null) throw new YelpException("invalid messages field in response"); Double code = JsonLibrary.getJsonDouble(messages, "code"); if (code == null) throw new YelpException("invalid code field in response"); if (code.intValue() != 0) { String message = ""; String text = JsonLibrary.getJsonString(messages, "text"); if (text != null) message = text; throw new YelpStatusException(message, code.intValue()); } } private LocalSearchResult parseResult(JSONValue value) throws YelpException { JSONObject obj = value.isObject(); if (obj == null) throw new YelpException("invalid business result"); String id = JsonLibrary.getJsonString(obj, "id"); if (id == null) throw new YelpException("invalid id field for business object"); String name = JsonLibrary.getJsonString(obj, "name"); if (name == null) throw new YelpException("invalid name field for business object"); Double lat = JsonLibrary.getJsonDouble(obj, "latitude"); Double lon = JsonLibrary.getJsonDouble(obj, "longitude"); if (lat == null || lon == null) return null; Double rating = JsonLibrary.getJsonDouble(obj, "avg_rating"); if (rating == null) throw new YelpException("invalid avg_rating field for business object"); String url = JsonLibrary.getJsonString(obj, "url"); String address = JsonLibrary.getJsonString(obj, "address1"); String city = JsonLibrary.getJsonString(obj, "city"); String region = JsonLibrary.getJsonString(obj, "state"); String zip = JsonLibrary.getJsonString(obj, "zip"); String phone = JsonLibrary.getJsonString(obj, "phone"); String ratingUrl = JsonLibrary.getJsonString(obj, "rating_img_url"); String ratingUrlSmall = JsonLibrary.getJsonString(obj, "rating_img_url_small"); LocalSearchResult result = new LocalSearchResult(); result.setId(id); result.setName(name); result.setUrl(url); result.setLat(lat); result.setLon(lon); result.setRating(rating); result.setMaxRating(5.0); result.setAddress(address); result.setCity(city); result.setRegion(region); result.setZip(zip); result.setPhoneNumber(phone); result.setRatingUrl(ratingUrl); result.setRatingUrlSmall(ratingUrlSmall); JSONArray categories = JsonLibrary.getJsonArray(obj, "categories"); for (int i = 0; i < categories.size(); i++) { JSONValue cValue = categories.get(i); JSONObject cObject = cValue.isObject(); String cName = JsonLibrary.getJsonString(cObject, "name"); result.getCategories().add(cName); } return result; } } }